﻿using System;
using System.Collections.ObjectModel;
using Peter.Common;
using Peter.Sdw.Data;

namespace Peter.Sdw.Logic
{
   /// <summary>
   /// The view model for editing an item.
   /// </summary>
   public class EditItemModel : ViewModelBase
   {
      private string m_EndStyle;
      private string m_StartStyle;

      private bool m_CanSpan;
      private bool m_HasLinks;
      private bool m_IsLoading;
      private bool m_SpansMulitiple;

      private int m_StartIndex;
      private int m_EndIndex;

      private Style m_SelectedStyle;
      private readonly ObservableCollection<Link> m_Links;
      private readonly ObservableCollection<Style> m_Styles;

      /// <summary>
      /// Initializes a new edit item model.
      /// </summary>
      public EditItemModel ()
      {
         this.m_Links = new ObservableCollection <Link> ();
         this.m_Styles = new ObservableCollection <Style> ();
         WebQueue.Instance.WebGetComplete += this.OnGetCompleted;
      }
      
      /// <summary>
      /// Gets or Sets if we are loading data.
      /// </summary>
      public bool IsLoading
      {
         get { return this.m_IsLoading; }
         set
         {
            this.m_IsLoading = value;
            this.RaisePropertyChanged ("IsLoading");
         }
      }

      /// <summary>
      /// Gets or Sets the start index.
      /// </summary>
      public int StartIndex
      {
         get { return this.m_StartIndex; }
         set
         {
            if (this.m_StartIndex != value) {
               this.m_StartIndex = value;
               this.RaisePropertyChanged ("StartIndex");
            }
         }
      }

      /// <summary>
      /// Gets or Sets the end index.
      /// </summary>
      public int EndIndex
      {
         get { return this.m_EndIndex; }
         set
         {
            if (this.m_EndIndex != value) {
               this.m_EndIndex = value;
               this.RaisePropertyChanged ("EndIndex");
            }
         }
      }

      /// <summary>
      /// Gets or Sets if the current item has links or not.
      /// </summary>
      public bool HasLinks
      {
         get { return this.m_HasLinks; }
         set
         {
            this.m_HasLinks = value;
            this.RaisePropertyChanged ("HasLinks");
         }
      }

      /// <summary>
      /// Gets or Sets the start style.
      /// </summary>
      public string StartStyle
      {
         get { return this.m_StartStyle; }
         set
         {
            this.m_StartStyle = value;
            this.RaisePropertyChanged ("StartStyle");
         }
      }

      /// <summary>
      /// Gets or Sets the end style.
      /// </summary>
      public string EndStyle
      {
         get { return this.m_EndStyle; }
         set
         {
            this.m_EndStyle = value;
            this.RaisePropertyChanged ("EndStyle");
         }
      }

      /// <summary>
      /// Gets or Sets if this item can span multiple entries.
      /// </summary>
      public bool CanSpan
      {
         get { return this.m_CanSpan; }
         set
         {
            this.m_CanSpan = value;
            this.RaisePropertyChanged ("CanSpan");
         }
      }

      /// <summary>
      /// Gets or Sets if the style spans mulitple entries.
      /// </summary>
      public bool SpansMulitiple
      {
         get { return this.m_SpansMulitiple; }
         set
         {
            this.m_SpansMulitiple = value;
            this.RaisePropertyChanged ("SpansMulitiple");
         }
      }

      /// <summary>
      /// Gets or Sets the selected style.
      /// </summary>
      public Style SelectedStyle
      {
         get { return this.m_SelectedStyle; }
         set
         {
            this.m_SelectedStyle = value;
            this.RaisePropertyChanged ("SelectedStyle");
            if (this.m_SelectedStyle == null) return;
            this.EndStyle = this.SelectedStyle.End;
            this.StartStyle = this.SelectedStyle.Start;
            this.EndIndex = this.SelectedStyle.EndIndex;
            this.StartIndex = this.SelectedStyle.StartIndex;
            this.SpansMulitiple = this.SelectedStyle.SpansMultiple;
         }
      }

      /// <summary>
      /// Gets the parent id.
      /// </summary>
      public int ParentId { get; private set; }

      /// <summary>
      /// Gets the item type.
      /// </summary>
      public ItemType ItemType { get; private set; }

      /// <summary>
      /// Gets the parent item type.
      /// </summary>
      public ItemType ParentType { get; private set; }

      /// <summary>
      /// Gets the links.
      /// </summary>
      public ObservableCollection<Link> Links { get { return this.m_Links; } }

      /// <summary>
      /// Gets the styles.
      /// </summary>
      public ObservableCollection<Style> Styles { get { return this.m_Styles; } }

      /// <summary>
      /// Gets the data from the server.
      /// </summary>
      public void Get (ItemType parentType, ItemType itemType, int parentId)
      {
         this.IsLoading = true;
         this.ItemType = itemType;
         this.ParentId = parentId;
         this.ParentType = parentType;
         this.Links.Clear();
         this.Styles.Clear();
         if (this.ItemType == ItemType.Header) {
            WebQueue.Instance.Get (string.Format (Constants.URL_GET_HEADER, this.ParentType, this.ParentId));
         } else if (this.ItemType == ItemType.Header) {
            WebQueue.Instance.Get (string.Format (Constants.URL_GET_FOOTER, this.ParentType, this.ParentId));
         } else if (this.ItemType == ItemType.Entry) {
            //WebQueue.Instance.Get (string.Format (Constants.URL_GET_FOOTER, this.ParentType, this.ParentId));
         }
      }

      /// <summary>
      /// Adds the given styles to the current list.
      /// </summary>
      /// <param name="response"></param>
      public void AddStyles (dynamic response)
      {
         if (response.styles != null) {
            foreach (var style in response.styles) {
               this.Styles.Add (new Style {
                  Id = style.id,
                  Start = style.start,
                  End = style.end,
                  StartIndex = style.startindex,
                  EndIndex = style.endindex,
                  SpansMultiple = style.multispan
               });
            }
         }
      }

      /// <summary>
      /// Adds the given links to the current list.
      /// </summary>
      /// <param name="response"></param>
      public void AddLinks (dynamic response)
      {
         if (response.links != null) {
            foreach (var style in response.links) {
               this.Links.Add (new Link {
                  Id = style.id,
                  Url = style.url,
                  NewWindow = style.newwindow,
                  StartIndex = style.startindex,
                  EndIndex = style.endindex
               });
            }
         }
      }

      /// <summary>
      /// Occurs when a web request is completed.
      /// </summary>
      /// <param name="sender">WebQueue.</param>
      /// <param name="e">WebRequestEventArgs</param>
      private void OnGetCompleted (object sender, WebRequestEventArgs e)
      {
         try {
            if (e.Url == string.Format (Constants.URL_GET_HEADER, this.ParentType, this.ParentId)) {
               if (e.Response.status == Constants.SUCCESS) {
                  Console.WriteLine (Properties.Resources.Data_received);
                  this.AddStyles (e.Response);
               }
               this.IsLoading = false;
            } else if (e.Url == string.Format (Constants.URL_GET_FOOTER, this.ParentType, this.ParentId)) {
               if (e.Response.status == Constants.SUCCESS) {
                  Console.WriteLine (Properties.Resources.Data_received);
                  this.AddStyles (e.Response);
                  this.AddLinks (e.Response);
               }
               this.IsLoading = false;
            }
         } catch (Exception ex) {
            Console.Error.WriteLine (ex.Message);
         }
      }
   }
}
